package com.huixuebao.exchange.service.Impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huixuebao.common.bean.ApiResult;
import com.huixuebao.common.enumeration.ResultCodeEnum;
import com.huixuebao.common.util.ConvertUtils;
import com.huixuebao.exchange.dto.CategoryDTO;
import com.huixuebao.exchange.dto.ContentDTO;
import com.huixuebao.exchange.dto.CourseDTO;
import com.huixuebao.exchange.entity.BaseDivision;
import com.huixuebao.exchange.entity.CourseEntity;
import com.huixuebao.exchange.entity.MechanismEntity;
import com.huixuebao.exchange.mapper.BaseDivisionMapper;
import com.huixuebao.exchange.mapper.CategoryMapper;
import com.huixuebao.exchange.mapper.CourseMapper;
import com.huixuebao.exchange.mapper.MechanismMapper;
import com.huixuebao.exchange.service.CategoryService;
import com.huixuebao.exchange.service.CourseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper,CourseEntity> implements CourseService {
    @Autowired
    MechanismMapper mechanismMapper;
    @Autowired
    CourseMapper courseMapper;
    @Autowired
    CategoryService categoryService;
    @Autowired
    BaseDivisionMapper baseDivisionMapper;
    @Autowired
    CategoryMapper categoryMapper;
    @Override
    public ApiResult<List<CourseDTO>> getAllCourse(Integer current,Integer size, String cityId, Double axisX, Double axisY, Integer distance, String categoryId, String brand,
                                                   String courseName) {
        ApiResult apiResult = new ApiResult();
        List<MechanismEntity> allSatisfiedMerchants = new ArrayList<>();
        try {
            if (ObjectUtil.isNotNull(current) && ObjectUtil.isNotNull(size)) {
                if (StrUtil.isNotBlank(cityId)) {
                    List<String> allCityIds = getChilds(cityId);
                    allCityIds.add(cityId);
                    allSatisfiedMerchants = mechanismMapper.selectList(new LambdaQueryWrapper<MechanismEntity>()
                            .in(MechanismEntity::getCityId, cityId)
                            .like(StrUtil.isNotBlank(brand), MechanismEntity::getBrand, brand));
                } else {
                    //cityId为空情况下
                    List<MechanismEntity> allMerchants = mechanismMapper.selectList(new LambdaQueryWrapper<MechanismEntity>()
                            .like(StrUtil.isNotBlank(brand), MechanismEntity::getBrand, brand));
                    // 找到全部距离上小于distance的机构
                    for (MechanismEntity mechanismEntity : allMerchants) {
                        if (StrUtil.isNotBlank(mechanismEntity.getAxisX()) && StrUtil.isNotBlank(mechanismEntity.getAxisY())) {
                            double d = getDistanceFromTwoPoints(axisX, axisY, Double.parseDouble(mechanismEntity.getAxisX()), Double.parseDouble(mechanismEntity.getAxisY()));
                            log.info("打印d{}:" + d);
                            if (d <= distance) {
                                allSatisfiedMerchants.add(mechanismEntity);
                            }
                        }
                    }
                }
                IPage<CourseEntity> page = new Page<>(current, size);
                List<String> userNumbers = allSatisfiedMerchants.stream().map(MechanismEntity::getUserNubmer).collect(Collectors.toList());
                //课程分类id
                List<String> categoryIds = null;
                if (StrUtil.isNotBlank(categoryId)) {
                    ApiResult<List<CategoryDTO>> apiResults = categoryService.listAllCategoryByPid(categoryId);
                    List<CategoryDTO> categories = apiResults.getData();
                    categoryIds = categories.stream().map(CategoryDTO::getId).collect(Collectors.toList());
                }
                if (CollUtil.isNotEmpty(userNumbers)) {
                    LambdaQueryWrapper<CourseEntity> lambdaQuery = new LambdaQueryWrapper<CourseEntity>().in(userNumbers.size()>0,CourseEntity::getMechanismNo,userNumbers);

                    lambdaQuery.in(StrUtil.isNotBlank(categoryId), CourseEntity::getCategoryId, categoryIds)
                            .like(StrUtil.isNotBlank(courseName), CourseEntity::getCourseName, courseName)
                            .like(StrUtil.isNotBlank(brand), CourseEntity::getBrand, brand);
                    IPage<CourseEntity> entityIPage = courseMapper.selectPage(page, lambdaQuery);
                    IPage<CourseDTO> returnCoursePage = ConvertUtils.convertToDTOPage(entityIPage, CourseDTO.class);
                    List<CourseDTO> dataList = returnCoursePage.getRecords();
                    for (CourseDTO courseDto: dataList) {
                        for (MechanismEntity mechanismAddress:allSatisfiedMerchants) {
                            if(courseDto.getMechanismNo().equals(mechanismAddress.getUserNubmer())){
                                courseDto.setMechanismAddress(mechanismAddress.getAddress());
                            }
                        }
                    }
                    returnCoursePage.setRecords(dataList);
                    apiResult.setData(returnCoursePage);
                    apiResult.setSuccess(true);
                    apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
                    apiResult.setMessage("temp获取课程信息成功!!");
                }else {
                    apiResult.setSuccess(false);
                    apiResult.setCode(ResultCodeEnum.FAILURE.getCode());
                    apiResult.setMessage("当前地区未有查询到相应机构!!");
                }
            }else {
                List<CourseEntity> list = courseMapper.selectList(null);
                List<CourseDTO> dtoList = ConvertUtils.convertToDTOList(list, CourseDTO.class);
                apiResult.setData(dtoList);
                apiResult.setSuccess(true);
                apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
                apiResult.setMessage("获取课程列表信息成功!!");
            }
        } catch (Exception e) {
            log.info("获取课程信息失败!!");
            apiResult.setSuccess(false);
            apiResult.setCode(ResultCodeEnum.FAILURE.getCode());
            apiResult.setMessage("temp获取课程信息失败！！");
        }
        return apiResult;
    }

    /**
     * 获取课程详情信息content
     * @param id
     * @return
     */
    @Override
    public ApiResult getCourseContent(String id) {
        ApiResult apiResult = new ApiResult();
        try {
            ContentDTO contentDTO = new ContentDTO();
            CourseEntity courseId = courseMapper.selectById(id);
            contentDTO.setContent(courseId.getContent());
            apiResult.setData(contentDTO);
            apiResult.setSuccess(true);
            apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
            apiResult.setMessage("获取课程详情信息成功！！");
        }catch (Exception e){
            apiResult.setSuccess(true);
            apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
            apiResult.setMessage("获取课程详情信息失败！！");
        }
        return apiResult;
    }

    //根据中心点，计算出坐标之间对距离，
    private double getDistanceFromTwoPoints(double lat_a, double lng_a, double lat_b, double lng_b) {
        Double PI = Math.PI;
        Double PK = 180 / PI;

        double t1 = Math.cos(lat_a / PK) * Math.cos(lng_a / PK) * Math.cos(lat_b / PK) * Math.cos(lng_b / PK);
        double t2 = Math.cos(lat_a / PK) * Math.sin(lng_a / PK) * Math.cos(lat_b / PK) * Math.sin(lng_b / PK);
        double t3 = Math.sin(lat_a / PK) * Math.sin(lat_b / PK);

        double tt = Math.acos(t1 + t2 + t3);

        return 6366000 * tt;

    }

    private List<String> getChilds(String cityId) {
        List<String> result = new ArrayList<>();
        List<String> childs = baseDivisionMapper.selectList(new LambdaQueryWrapper<BaseDivision>().eq(BaseDivision::getPId, cityId)).stream().map(BaseDivision::getId).collect(Collectors.toList());
        result.addAll(childs);
        childs.stream().forEach(child -> {
            List<String> list = baseDivisionMapper.selectList(new LambdaQueryWrapper<BaseDivision>().eq(BaseDivision::getPId, child)).stream().map(BaseDivision::getId).collect(Collectors.toList());
            result.addAll(list);
        });
        return result;
    }

    /**
     * 获取课程详情信息
     * @param mechanismId
     * @return
     */
    @Override
    public ApiResult getCourseItem(Integer current,Integer size,String mechanismId){
        ApiResult apiResult = new ApiResult();
        try{
            if (ObjectUtil.isNotNull(current) && ObjectUtil.isNotNull(size)) {
                IPage<CourseEntity> page = new Page<>(current, size);
                LambdaQueryWrapper<CourseEntity> lambdaQuery = new LambdaQueryWrapper<CourseEntity>().eq(CourseEntity::getMechanismId,mechanismId);
                IPage<CourseEntity> entityPage = courseMapper.selectPage(page,lambdaQuery);
                IPage<CourseDTO> dtoPage = ConvertUtils.convertToDTOPage(entityPage,CourseDTO.class);
                apiResult.setData(dtoPage);
                apiResult.setSuccess(true);
                apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
                apiResult.setMessage("获取课程分页信息成功!!");

            }else {
                List<CourseEntity> courseList = courseMapper.selectList(new LambdaQueryWrapper<CourseEntity>().eq(CourseEntity::getMechanismId,mechanismId));
                List<CourseDTO> courseDTOList = ConvertUtils.convertToDTOList(courseList,CourseDTO.class);
                apiResult.setData(courseDTOList);
                apiResult.setSuccess(true);
                apiResult.setCode(ResultCodeEnum.SUCCESS.getCode());
                apiResult.setMessage("获取课程列表成功!!");
            }
        }catch (Exception e){
            log.info("获取课程信息异常！！");
            apiResult.setSuccess(false);
            apiResult.setCode(ResultCodeEnum.FAILURE.getCode());
            apiResult.setMessage("获取课程信息失败！！");
        }
        return apiResult;
    }
}
